# -*-coding:utf-8-*-
import multiprocessing as mp
import time
from concurrent.futures import ProcessPoolExecutor

"""
multiprocessing.Queue,Value,Lock,Array等对象传递给Pool()的解决方法(如果使用Process()不需要)
1.使用Manager需要生成另一个进程来托管Manager服务器
(!!!windows系统下没法fork进程,manager相关的对象必须在函数中定义和操作,manager中的value和array不是进程安全的!!!).
    with Manager() as m:
        que = m.Queue(10)
        p = m.Pool(3)
        r = p.starmap_async(worker1, ((i, que) for i in range(6)), callback=callback)
        p.close()
        p.join()
2.使用初始化程序在池创建时传递常规multiprocessing.Queue()这将使Queue实例在所有子进程中全局共享
    que = multiprocessing.Queue(10)
    p = m.Pool(3, initializer=init, initargs=(que,))
    r = p.map_async(worker2, (i for i in range(6)), callback=callback)
"""

class MyProcess(mp.Process):
    def __init__(self, x, q):
        super().__init__()
        self._x = x
        self._q = q

    def run(self) -> None:
        print('进程', self._x, '执行')
        self._q.put(self._x)
        time.sleep(1)

def worker1(x, q):
    print('进程', x, '执行')
    q.put(x)
    time.sleep(1)
    return x

def worker2(x):
    print('进程', x, '执行')
    q1.put(x)
    time.sleep(1)
    return x

def callback(i):
    # callback在主进程中运行
    print('回调', i)

def init(_q1):
    global q1
    q1 = _q1

# 通过Pool创建进程
def main1():
    m = mp.Manager()
    que = m.Queue(10)
    p = mp.Pool(3)
    r = p.starmap_async(worker1, ((i, que) for i in range(6)), callback=callback)
    p.close()
    p.join()
    print('完成', r.get(), que.get())

# 通过Pool创建进程
def main2():
    que = mp.Queue(10)
    p = mp.Pool(3, initializer=init, initargs=(que,))
    r = p.map_async(worker2, (i for i in range(6)), callback=callback)
    p.close()
    p.join()
    print('完成', r.get(), que.get())

# 直接创建进程
def main3():
    que = mp.Queue(10)
    p1 = mp.Process(target=worker1, args=(1, que))
    p2 = MyProcess(2, que)
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    print('完成', que.get())

# 通过ProcessPoolExecutor创建进程
def main4():
    que = mp.Manager().Queue(10)
    with ProcessPoolExecutor(4) as executor:
        rs = executor.map(worker1, [1, 2, 3], [que, que, que])
        print(list(rs))
    print('完成', que.get())


if __name__ == '__main__':
    main2()